package com.dlc.apk.api

import com.dlc.apk.api.HttpLogInterceptor
import com.dlc.apk.base.BaseApp
import com.dlc.apk.utils.GsonUtil
import com.dlc.apk.utils.IOUtils
import com.dlc.apk.utils.LogPlus
import com.franmontiel.persistentcookiejar.PersistentCookieJar
import com.franmontiel.persistentcookiejar.cache.SetCookieCache
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.TypeAdapter
import com.google.gson.TypeAdapterFactory
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import com.google.gson.stream.JsonWriter
import com.jeremyliao.liveeventbus.LiveEventBus
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.ResponseBody
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.io.IOException
import java.util.concurrent.TimeUnit


/**
 * @author We
 */
class ApiManager {
    private lateinit var retrofit: Retrofit
    lateinit var apiService: IServerApi
        private set

    init {
        initHttpClient()
    }

    private fun initHttpClient() {
        val httpClientBuilder = OkHttpClient.Builder()
        val cookieJar = PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(BaseApp.instance))
        httpClientBuilder
            .cookieJar(cookieJar)
            .addInterceptor(HttpLogInterceptor("ApiManager"))
            .addInterceptor { chain: Interceptor.Chain ->
                val request = chain.request()
                var response = chain.proceed(request)
                /////////////////////////解决后台接口在"非正常数据"时返回 data=[] //////////////////////////////
                if (HttpLogInterceptor.isPlaintext(response.body()?.contentType())) {
                    try {
                        val bytes = IOUtils.toByteArray(response.body()?.byteStream())
                        val baseResponse = GsonUtil.instance.parseJsonStrToObj(String(bytes), BaseResponseModel::class.java)
                        if (baseResponse != null) {
                            if (baseResponse.code != ApiConstants.CODE_SUCCESS) {
                                LogPlus.e("###data is ->${baseResponse.data}")
                                baseResponse.data = null
                                LiveEventBus.get(API_CODE_NOT_SUCCESS).post(baseResponse.msg)
                            }
                            response = response.newBuilder().body(ResponseBody.create(response.body()?.contentType(), GsonUtil.instance.parseObjToJsonStr(baseResponse))).build()
                        }
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }
                /////////////////////////解决后台接口在"非正常数据"时返回 data=[] //////////////////////////////
                response
            }
            .connectTimeout(DEFAULT_TIMEOUT.toLong(), TimeUnit.SECONDS)
            .writeTimeout(DEFAULT_TIMEOUT.toLong(), TimeUnit.SECONDS)
            .readTimeout(DEFAULT_TIMEOUT.toLong(), TimeUnit.SECONDS)

        val gson = GsonBuilder()
            /*.registerTypeAdapter(Object::class.java, GsonTypeAdapter())*/
            .registerTypeAdapterFactory(IgnoreFailureTypeAdapterFactory())//忽略值类型错误
            .create()

        retrofit = Retrofit.Builder()
            .baseUrl(mBaseUrl)
            .addConverterFactory(GsonConverterFactory.create(gson)) //gson converter
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//支持RxJava2
            .client(httpClientBuilder.build())
            .build()
        apiService = retrofit.create(IServerApi::class.java)
    }


    companion object {
        private var mApiManager: ApiManager? = null
        private const val DEFAULT_TIMEOUT = 15
        var mBaseUrl = ApiConstants.BASE_URL
        const val API_CODE_NOT_SUCCESS = "API_CODE_NOT_SUCCESS"

        @JvmStatic
        val instance: ApiManager
            get() {
                if (mApiManager == null) {
                    mApiManager = ApiManager()
                }
                return mApiManager!!
            }
    }

    class GsonTypeAdapter : TypeAdapter<Any?>() {
        @Throws(IOException::class)
        override fun read(`in`: JsonReader): Any? {
            // 反序列化
            return when (`in`.peek()) {
                JsonToken.BEGIN_ARRAY -> {
                    val list: MutableList<Any?> = ArrayList()
                    `in`.beginArray()
                    while (`in`.hasNext()) {
                        list.add(read(`in`))
                    }
                    `in`.endArray()
                    list
                }
                JsonToken.BEGIN_OBJECT -> {
                    val map: MutableMap<String, Any?> = HashMap()
                    `in`.beginObject()
                    while (`in`.hasNext()) {
                        map[`in`.nextName()] = read(`in`)
                    }
                    `in`.endObject()
                    map
                }
                JsonToken.STRING -> `in`.nextString()
                JsonToken.NUMBER -> {
                    val numStr = `in`.nextString()
                    LogPlus.e("###numStr->$numStr")
                    /**
                     * 改写数字的处理逻辑，将数字值分为整型与浮点型。
                     */
                    val dbNum = `in`.nextDouble()
                    // 数字超过long的最大值，返回浮点类型
                    if (dbNum > Long.MAX_VALUE) {
                        return dbNum
                    }

                    // 判断数字是否为整数值
                    val lngNum = dbNum.toLong()
                    if (dbNum == lngNum.toDouble()) {
                        lngNum
                    } else {
                        dbNum
                    }
                }
                JsonToken.BOOLEAN -> `in`.nextBoolean()
                JsonToken.NULL -> {
                    `in`.nextNull()
                    null
                }
                else -> throw IllegalStateException()
            }
        }

        @Throws(IOException::class)
        override fun write(out: JsonWriter?, value: Any?) {
            // 序列化不处理
        }
    }

    /**
     * 忽略值错误(类型错误等)
     */
    internal class IgnoreFailureTypeAdapterFactory : TypeAdapterFactory {
        override fun <T> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T> {
            val delegate = gson.getDelegateAdapter(this, type)
            return createCustomTypeAdapter(delegate)
        }

        private fun <T> createCustomTypeAdapter(delegate: TypeAdapter<T?>): TypeAdapter<T> {
            return object : TypeAdapter<T>() {
                @Throws(IOException::class)
                override fun write(out: JsonWriter, value: T?) {
                    delegate.write(out, value)
                }

                @Throws(IOException::class)
                override fun read(`in`: JsonReader): T? {
                    return try {
                        delegate.read(`in`)
                    } catch (e: java.lang.Exception) {
                        `in`.skipValue()
                        null
                    }
                }
            }
        }
    }
}